package com.mxx.common.generator.db;

import com.mxx.common.core.UniquelyList;
import com.mxx.common.generator.Constant;
import com.mysql.cj.MysqlType;
import com.mysql.cj.jdbc.result.ResultSetImpl;

import java.sql.*;

public class MysqlTableReader implements TableReader {

    private Connection conn;

    public MysqlTableReader(Connection conn) {
        this.conn = conn;
    }

    @Override
    public Table reader(String tableName) throws SQLException {
        UniquelyList<String, Table> uniquelyList = readTable(tableName);
        return uniquelyList.get(0);
    }

    @Override
    public UniquelyList<String, Table> readAll() throws SQLException {
        return readTable("%");
    }

    protected UniquelyList<String, Table> readTable(String tableName) throws SQLException {
        UniquelyList<String, Table> uniquelyList = new UniquelyList<>(Table::getTableName);
        DatabaseMetaData db = conn.getMetaData();
        ResultSet rs = db.getTables(conn.getCatalog(), conn.getCatalog(), tableName, new String[]{"TABLE"});


        while (rs.next()) {
            Table table = new Table()
                    .setTableName(rs.getString(Constant.TableMetadata.TABLE_NAME))
                    .setTableType(rs.getString(Constant.TableMetadata.TABLE_TYPE))
                    .setDatabase(rs.getString(Constant.TableMetadata.TABLE_CAT))
                    .setRemark(rs.getString(Constant.TableMetadata.REMARKS));
            uniquelyList.add(table);
        }
        rs.close();
        for (Table table : uniquelyList) {
            readField(db, table);
        }
        return uniquelyList;
    }

    protected void readField(DatabaseMetaData db, Table table) throws SQLException {
        ResultSetImpl rs = (ResultSetImpl) db.getColumns(conn.getCatalog(), conn.getCatalog(), table.getTableName(), null);
        while (rs.next()) {

            TableColumn tableColumn = new TableColumn()
                    .setColumnName(rs.getString(Constant.FieldMetadata.COLUMN_NAME))
                    .setColumnSize(rs.getInt(Constant.FieldMetadata.COLUMN_SIZE))
                    .setDefVal(rs.getString(Constant.FieldMetadata.COLUMN_DEF))
                    .setRemark(rs.getString(Constant.FieldMetadata.REMARKS))
                    .setMysqlType(MysqlType.getByJdbcType(JDBCType.valueOf(rs.getInt(Constant.FieldMetadata.DATA_TYPE)).getVendorTypeNumber()))
                    .setNullable(rs.getInt(Constant.FieldMetadata.NULLABLE) == 0)
                    .setTypeName(rs.getString(Constant.FieldMetadata.TYPE_NAME))
                    .setGenerated(rs.getString(Constant.FieldMetadata.IS_GENERATEDCOLUMN))
                    .setAutoincrement(rs.getString(Constant.FieldMetadata.IS_AUTOINCREMENT));
            table.addTableField(tableColumn);
        }
        rs.close();
        readIndex(db, table);
    }

    protected void readIndex(DatabaseMetaData db, Table table) throws SQLException {
        ResultSet rs = db.getIndexInfo(conn.getCatalog(), conn.getCatalog(), table.getTableName(), false, false);
        while (rs.next()) {
            table.getField(rs.getString(Constant.IndexMetadata.COLUMN_NAME))
                    .setNonUnique(rs.getBoolean(Constant.IndexMetadata.NON_UNIQUE))
                    .setIndexName(rs.getString(Constant.IndexMetadata.INDEX_NAME))
                    .setOrdinalPosition(rs.getInt(Constant.IndexMetadata.ORDINAL_POSITION))
                    .setType(rs.getInt(Constant.IndexMetadata.TYPE))
                    .setDesOrDesc(rs.getString(Constant.IndexMetadata.ASC_OR_DESC));
        }
        rs.close();
    }
}
